
#include "fifo.h"
#include "string.h"

static _fifo_str fifo_str;

int FifoInit(uint8_t *fifo_addr, uint32_t fifo_size)
{
	_fifo_str *p = &fifo_str;
	
	if(fifo_addr == NULL || fifo_size == 0)
		return -1;

	memset((char *)p, 0, sizeof(_fifo_str));
	p->buf = fifo_addr;
    p->in = 0;
    p->out = 0;
    p->size = fifo_size;
	return 0;
}

int FifoDataLen(void)
{
	_fifo_str *p = &fifo_str;
	
	return ((p->in - p->out) & (p->size - 1));
}

int FifoSpaceLen(void)
{
	_fifo_str *p = &fifo_str;
	
	return ((p->out - (p->in + 1)) & (p->size - 1));
}

int FifoRead(uint8_t *buf, uint32_t len)
{
	uint32_t cnt = 0, copy_len = 0;
	_fifo_str *p = &fifo_str;

	cnt = FifoDataLen();
	cnt = min(len, cnt);
	if((p->out + cnt) > p->size)
	{
		copy_len = p->size - p->out;
		memcpy(buf, p->buf + p->out, copy_len);
		memcpy(buf + copy_len, p->buf, cnt - copy_len);
	}
	else
	{
		memcpy(buf, p->buf + p->out, cnt);
	}
	p->out = (p->out + cnt) & (p->size - 1);
	return cnt;
}

int FifoWrite(uint8_t *buf, uint32_t len)
{
	uint32_t copy_len = 0;
	_fifo_str *p = &fifo_str;

	if(FifoSpaceLen() <= len)
	{
		p->out = (p->out + len) & (p->size - 1);
	}
	if((p->in + len) > p->size)
	{
		copy_len = p->size - p->out;
		memcpy(p->buf + p->in, buf, copy_len);
		memcpy(p->buf, buf + copy_len, len - copy_len);
	}
	else
	{
		memcpy(p->buf + p->in, buf, len);
	}
	p->in = (p->in + len) & (p->size - 1);
	
	return len;
}

void FifoClear(void)
{
	_fifo_str *p = &fifo_str;
	
    p->in = 0;
    p->out = 0;
}


